﻿// -------------------------------------------------------------------------
//    @FileName         :    NFServiceQuest.cpp
//    @Author           :    gaoyi
//    @Date             :    2025/1/15
//    @Email            :    445267987@qq.com
//    @Module           :    NFServiceQuest
//
// -------------------------------------------------------------------------

#include "NFServiceQuest.h"

#include <NFBagPageOpMgr.h>
#include <NFEventDisp.h>
#include <NFPacketSendUtil.h>
#include <NFPlayer.h>
#include <NFQuestPart.h>
#include <NFQuestUtil.h>
#include <NFServicePackage.h>
#include <DescStore/LoopQuestDesc.h>
#include <DescStore/QuestDesc.h>
#include <NFComm/NFPluginModule/NFCheck.h>
#include <NFLogicCommon/NFLogicShmTypeDefines.h>

#include "NFDropUtil.h"
#include "NFPackageUtil.h"
#include "NFPlayerUtil.h"
#include "NFServiceSkill.h"
#include "NFServiceSns.h"
#include "proto_cs_cmd.nanopb.h"

int NFServiceQuest::Accept(NFPlayer* pPlayer, int iQuestId, bool bNotCheckTeam, bool bNotNtf, bool bNotCheckFinish)
{
    int iRetCode = 0;
    CHECK_NULL(0, pPlayer);
    LoopQuest* pLoop = NULL;

    NFQuestPart* pQuestPart = pPlayer->GetPart<NFQuestPart>(PART_QUEST);
    CHECK_NULL(pPlayer->GetRoleID(), pQuestPart);

    auto pDesc = QuestDesc::Instance()->GetDesc(iQuestId);
    CHECK_NULL_WF(pPlayer->GetRoleID(), pDesc, "iQuestID:{}", iQuestId);

    auto pQuestNode = pQuestPart->GetQuestNode(iQuestId);
    if (pQuestNode)
    {
        LOGSVR_WARN("quest aleady accepetd: " << iQuestId);
        return ERR_CODE_QUEST_ALEADY_ACCEPT;
    }

    if (pDesc->quest_prev.size() > 0)
    {
        bool bPrev = false;
        for (int i = 0; i < (int)pDesc->quest_prev.size(); i++)
        {
            if (pDesc->quest_prev[i] > 0 && pQuestPart->IsFinished(pDesc->quest_prev[i]))
            {
                bPrev = true;
                break;
            }
        }
        CHECK_EXPR(bPrev, ERR_CODE_QUEST_PREV_NOT_FIN, "prev quest not finish:{}", iQuestId);
    }

    if (pDesc->type == E_Quest_Type_Normal) //单次
    {
        iRetCode = NFQuestUtil::CheckAcceptNormal(pQuestPart, pDesc, bNotCheckFinish);
        CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "check failed");
    }
    else if (pDesc->type == E_Quest_Type_Round) //循环
    {
        pLoop = pQuestPart->GetLoopQuest(pDesc->round_group_id);
        CHECK_NULL(pPlayer->GetRoleID(), pLoop);

        iRetCode = NFQuestUtil::CheckAcceptRound(pQuestPart, pLoop, pDesc, bNotCheckTeam);
        if (iRetCode == ERR_CODE_LEVEL_NOT_ENOUGH && pDesc->accept_with_team_member_num)
            return 0;

        CHECK_RET(iRetCode, "NFQuestUtil::CheckAcceptRound failed:{}", iQuestId);
        if (pLoop->giveup)
        {
            pLoop->giveup = false;
        }
    }
    else if (pDesc->type == E_Quest_Type_Protect) //护送
    {
        iRetCode = NFQuestUtil::CheckAcceptNormal(pQuestPart, pDesc, bNotCheckFinish);
        CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "check failed");

        auto pHis = pQuestPart->GetLoopQuestHis(iQuestId);
        CHECK_NULL(pPlayer->GetRoleID(), pHis);
        if (pHis->times_in_day >= (uint32_t)pDesc->day_max_times)
        {
            LOGSVR_WARN("quest day times use fin: " << iQuestId);
            return ERR_CODE_QUEST_ALEADY_FINISH;
        }
    }
    else if (pDesc->type == E_Quest_Type_Intrust) //委托
    {
        iRetCode = NFQuestUtil::CheckAcceptNormal(pQuestPart, pDesc, bNotCheckFinish);
        CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "check failed");
    }
    else if (pDesc->type == E_Quest_Type_Dungeon) //副本
    {
        iRetCode = NFQuestUtil::CheckAcceptNormal(pQuestPart, pDesc, bNotCheckFinish);
        CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "check failed");
    }
    else
    {
        LOGSVR_ERROR("quest type error : " << iQuestId << " " << pDesc->type);
        return -1;
    }

    NFBagPageOpMgr stBagPageOpMgr(pPlayer, EN_ICR_QUEST_ACCEPT, true);
    if (pDesc->accept_used_item > 0 && pDesc->accept_used_item_num > 0)
    {
        WillDelItemData stDelItemData;
        stDelItemData.m_iItemID = pDesc->accept_used_item;
        stDelItemData.m_iWantDelNum = pDesc->accept_used_item_num;
        iRetCode = stBagPageOpMgr.DelItems(stDelItemData);
        CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "DelItems");
    }

    if (pDesc->accept_use_gold > 0)
    {
        WillDelItemData stDelItemData;
        stDelItemData.m_iItemID = EN_ID_GOLD;
        stDelItemData.m_iWantDelNum = pDesc->accept_use_gold;
        iRetCode = stBagPageOpMgr.DelItems(stDelItemData);
        CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "DelItems");
    }

    if (pDesc->accept_use_money > 0)
    {
        WillDelItemData stDelItemData;
        stDelItemData.m_iItemID = EN_ID_MONEY;
        stDelItemData.m_iWantDelNum = pDesc->accept_use_money;
        iRetCode = stBagPageOpMgr.DelItems(stDelItemData);
        CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "DelItems");
    }

    std::vector<Item> vecItem;
    for (int i = 0; i < (int)pDesc->accept_item.size(); i++)
    {
        QuestItem& questItem = pDesc->accept_item[i];
        if (questItem.id > 0 && questItem.num > 0)
        {
            Item item;
            item.id = questItem.id;
            item.value = questItem.num;
            vecItem.push_back(item);
        }
    }

    iRetCode = stBagPageOpMgr.AddItems(vecItem);
    CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "AddItems");

    QuestNode* pNode = nullptr;
    if (pDesc->type == E_Quest_Type_Intrust)
    {
        return ERR_CODE_INVALID_REQ_PARAM;
    }

    pNode = pQuestPart->AddQuestNode(iQuestId);
    CHECK_NULL_WF(pPlayer->GetRoleID(), pNode, "AddQuestNode failed:{}", iQuestId);
    NFQuestUtil::InitQuestNode(pPlayer, pNode, pDesc);

    iRetCode = stBagPageOpMgr.Commit(true);
    CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "Commit iRetCode:{}", iRetCode);

    if (pDesc->type == E_Quest_Type_Round)
    {
    }
    pQuestPart->MarkDirty();

    if (!bNotNtf)
    {
        proto_ff::Proto_CSRsp resp;
        proto_ff::Proto_CSQuestAcceptRsp* acceptRsp = resp.mutable_quest_accept_rsp();
        pNode->ToPb(acceptRsp->mutable_quest());
        NFPacketSendUtil::SendToClient(pPlayer, E_CS_ACCEPT_QUEST_RSP, &resp);
    }

    LOGSVR_TRACE("accept quest success : " << iQuestId);
    NFEventDisp::OnQuestAccepted(pPlayer, iQuestId, pLoop);
    return 0;
}

int NFServiceQuest::Finish(NFPlayer* pPlayer, int iQuestId, int iItemId, int iItemQuality, uint64_t uItemGid, int iNextQuestId)
{
    int iRetCode = 0;
    NFQuestPart* pQuestPart = pPlayer->GetPart<NFQuestPart>(PART_QUEST);
    CHECK_NULL(pPlayer->GetRoleID(), pQuestPart);

    auto pQuestDesc = QuestDesc::Instance()->GetDesc(iQuestId);
    CHECK_NULL_WF(pPlayer->GetRoleID(), pQuestDesc, "iQuestID:{}", iQuestId);

    QuestNode* pNode = nullptr;
    if (pQuestDesc->type == proto_ff::E_Quest_Type_Intrust)
    {
        return proto_ff::ERR_CODE_INVALID_REQ_PARAM;
    }
    else
    {
        pNode = pQuestPart->GetQuestNode(iQuestId);
    }

    if (!pNode)
    {
        LOG_WARN(pPlayer->GetRoleID(), -1, "Quest not accpetd:{}", iQuestId);
        return proto_ff::ERR_CODE_QUEST_NOT_ACCEPT;
    }

    bool finished = true;
    int delItemID = 0;
    int delItemQuality = 0;
    uint64_t delItemUUID = 0;
    for (int i = 0; i < (int)pNode->event_node_list.size(); ++i)
    {
        QuestEventNode* pEventNode = &pNode->event_node_list[i];
        if (pEventNode->ev == proto_ff::E_QUEST_EVENT_USE_ITEM)
        {
            auto pItemDesc = ItemDesc::Instance()->GetDesc(iItemId);
            CHECK_NULL_WF(pPlayer->GetRoleID(), pItemDesc, "item id error: {} {}", iItemId, iQuestId);

            if (pItemDesc->item_type != pQuestDesc->complete_use_item_type || (pQuestDesc->complete_use_item_sub_type != 0 && pItemDesc->item_sub_type != pQuestDesc->complete_use_item_sub_type) || pItemDesc->item_lv < pQuestDesc->complete_use_item_level)
            {
                LOG_WARN(pPlayer->GetRoleID(), -1, "Used Item can not complete this quest:{}", iItemId);
                finished = false;
                break;
            }

            if (pItemDesc->item_type == proto_ff::EN_ITEM_TYPE_EQUIP || pItemDesc->item_type == proto_ff::EN_ITEM_TYPE_PARTNER_EQUIP || pItemDesc->item_type == proto_ff::EN_ITEM_TYPE_RUNE || pItemDesc->item_type == proto_ff::EN_ITEM_TYPE_TREASUREMAP || pItemDesc->item_type ==
                proto_ff::EN_ITEM_TYPE_BUFF_EQUIP)
            {
                auto pGridItem = NFServicePackage::GetItemByItemIdAndUUID(pPlayer, iItemId, uItemGid);
                if (pGridItem == nullptr)
                {
                    LOG_WARN(pPlayer->GetRoleID(), -1, "item not found: {} {}", iItemId, uItemGid)
                    finished = false;
                    break;
                }

                if (pGridItem->GetItemID() != iItemId)
                {
                    LOG_ERR(pPlayer->GetRoleID(), -1, "item id error: {} {} {}", pGridItem->GetItemID(), iItemId, uItemGid)
                    return -1;
                }
                delItemUUID = uItemGid;
            }
            else if (pItemDesc->item_type == proto_ff::EN_ITEM_TYPE_RANDOM_QUALITY)
            {
                delItemQuality = iItemQuality;
            }

            delItemID = iItemId;
        }
        else if (pEventNode->ev == proto_ff::E_QUEST_EVENT_CONSUME_ITEM)
        {
            auto pItemDesc = ItemDesc::Instance()->GetDesc(pEventNode->condition);
            CHECK_NULL_WF(pPlayer->GetRoleID(), pItemDesc, "condition id error: {} {}", pEventNode->condition, iQuestId);
            if (pItemDesc->item_type == proto_ff::EN_ITEM_TYPE_EQUIP || pItemDesc->item_type == proto_ff::EN_ITEM_TYPE_PARTNER_EQUIP || pItemDesc->item_type == proto_ff::EN_ITEM_TYPE_RUNE || pItemDesc->item_type == proto_ff::EN_ITEM_TYPE_TREASUREMAP || pItemDesc->item_type ==
                proto_ff::EN_ITEM_TYPE_BUFF_EQUIP)
            {
                auto pGridItem = NFServicePackage::GetItemByItemIdAndUUID(pPlayer, iItemId, uItemGid);
                if (pGridItem == nullptr)
                {
                    LOG_WARN(pPlayer->GetRoleID(), -1, "item not found: {} {}", iItemId, uItemGid)
                    finished = false;
                    break;
                }

                if (pGridItem->GetItemID() != iItemId || iItemId != pEventNode->condition)
                {
                    LOG_ERR(pPlayer->GetRoleID(), -1, "item type error: {} {} {} {}", pGridItem->GetItemID(), iItemId, pEventNode->condition, uItemGid)
                    return -1;
                }
                delItemUUID = uItemGid;
            }
            else if (pItemDesc->item_type == proto_ff::EN_ITEM_TYPE_RANDOM_QUALITY)
            {
                CHECK_EXPR(iItemId == pEventNode->condition, proto_ff::ERR_CODE_INVALID_REQ_PARAM, "item id error:{} {} {} ", iItemId, iQuestId, pEventNode->condition);
                delItemQuality = iItemQuality;
            }
        }
        else if (pEventNode->ev == proto_ff::E_QUEST_EVENT_JOIN_GUILD)
        {
            if (NFServiceSns::IsInGuild(pPlayer) == false)
            {
                LOG_WARN(pPlayer->GetRoleID(), -1, "player no guild!");
                finished = false;
                break;
            }
        }
        else
        {
            if (pEventNode->condition_value > pEventNode->value)
            {
                finished = false;
                LOG_WARN(pPlayer->GetRoleID(), -1, "Quest Condition not complete:{} {} {} {}", iQuestId, pEventNode->ev, pEventNode->condition_value, pEventNode->value);
                break;
            }
        }
    }
    if (finished == false)
    {
        return proto_ff::ERR_CODE_QUEST_NOT_COMPLETE;
    }

    if (iNextQuestId == 0 && pQuestDesc->quest_next > 0)
    {
        LOG_DEBUG(pPlayer->GetRoleID(), "auto set next quest:{} -> {}", iQuestId, pQuestDesc->quest_next);
        iNextQuestId = pQuestDesc->quest_next;
    }

    if (iNextQuestId > 0)
    {
        auto pNextDesc = QuestDesc::Instance()->GetDesc(iNextQuestId);
        CHECK_NULL_WF(pPlayer->GetRoleID(), pNextDesc, "quest id error: {}", iNextQuestId);

        if (pQuestPart->GetQuestNode(iNextQuestId))
        {
            //如果已完成就放弃自动接取
            //自动接取已完成任务
            LOG_DEBUG(pPlayer->GetRoleID(), "next quest already finish or accepted:{}", iNextQuestId);
            iNextQuestId = 0;
        }
        else
        {
            iRetCode = NFQuestUtil::CheckAcceptAfterFinish(iQuestId, iNextQuestId, pQuestPart);
            CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "check accept next failed:{} ", iNextQuestId);
        }
    }

    iRetCode = GetAward(pPlayer, iQuestId, delItemID, delItemQuality, delItemUUID);
    CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "Get Award Failed:{}", iQuestId);

    if (iNextQuestId)
    {
        // accept:
        iRetCode = Accept(pPlayer, iNextQuestId, false, false, true);
        CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "Accept Next Quest Failed:{}", iNextQuestId);
    }

    return iRetCode;
}

int NFServiceQuest::GetExpRateForLoopQuest(NFPlayer* pPlayer, const E_LoopQuest* pLoopDesc, LoopQuest* pLoop, NFBagPageOpMgr* pBagPageOpMgr, float& expRate)
{
    int iRetCode = 0;
    CHECK_NULL(0, pPlayer);
    CHECK_NULL(0, pLoopDesc);
    CHECK_NULL(0, pLoop);
    CHECK_NULL(0, pBagPageOpMgr);

    expRate = 1.0f;
    if (pLoopDesc->daily_times > 0)
    {
        bool crit = false;
        if (pLoopDesc->daily_crit_times > 0 && (pLoop->crit_times < pLoopDesc->daily_crit_times || pLoopDesc->daily_crit_times == 0))
        {
            if (pLoopDesc->daily_crit_item && pLoopDesc->daily_crit_item_num)
            {
                bool enough = false;
                iRetCode = pBagPageOpMgr->HaveEnoughItem(pLoopDesc->daily_crit_item, pLoopDesc->daily_crit_item_num, enough);
                CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "HaveEnoughItemBySuitableBag failed:{} {} {}", pLoopDesc->daily_crit_item, pLoopDesc->daily_crit_item_num, pLoopDesc->id);
                if (enough)
                {
                    iRetCode = pBagPageOpMgr->DelItems(pLoopDesc->daily_crit_item, pLoopDesc->daily_crit_item_num);
                    CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "del item failed:{} {} {}", pLoopDesc->daily_crit_item, pLoopDesc->daily_crit_item_num, pLoopDesc->id);
                    crit = true;
                    expRate = 1.0f * pLoopDesc->daily_crit;
                    pLoop->crit_times += 1;
                }
            }
            else
            {
                crit = true;
                expRate = 1.0f * pLoopDesc->daily_crit;
                pLoop->crit_times += 1;
            }
        }
        if (crit == false && (pLoopDesc->daily_no_crit_times == 0 || pLoop->no_crit_times < pLoopDesc->daily_no_crit_times))
        {
            crit = true;
            pLoop->no_crit_times += 1;
        }
        if (!crit)
        {
            expRate = 0;
        }
        else
        {
            expRate *= 1.0f + pLoopDesc->award_increte * (pLoop->node_index > 0 ? pLoop->node_index : 1);
        }
    }
    LOG_DEBUG(pPlayer->GetRoleID(), "questId:{} Exp Rate:{}", pLoop->quest_id, expRate);
    return expRate;
}

int NFServiceQuest::GetAward(NFPlayer* pPlayer, int iQuestID, int iItemID, int iItemQuality, uint64_t uItemGID)
{
    int iRetCode = 0;
    CHECK_NULL(0, pPlayer);
    NFQuestPart* pQuestPart = pPlayer->GetPart<NFQuestPart>(PART_QUEST);
    CHECK_NULL(pPlayer->GetRoleID(), pQuestPart);

    auto pQuestDesc = QuestDesc::Instance()->GetDesc(iQuestID);
    CHECK_NULL_WF(pPlayer->GetRoleID(), pQuestDesc, "iQuestID:{}", iQuestID);

    QuestNode* pNode = nullptr;
    if (pQuestDesc->type == proto_ff::E_Quest_Type_Intrust)
    {
        return proto_ff::ERR_CODE_INVALID_REQ_PARAM;
    }
    else
    {
        pNode = pQuestPart->GetQuestNode(iQuestID);
    }

    if (!pNode)
    {
        LOG_WARN(pPlayer->GetRoleID(), -1, "Quest not accpetd:{}", iQuestID);
        return proto_ff::ERR_CODE_QUEST_NOT_ACCEPT;
    }

    NFBagPageOpMgr stBagPageOpMgr(pPlayer, EN_ICR_QUEST_COMPELET_COST, true);
    for (int i = 0; i < (int)pNode->event_node_list.size(); ++i)
    {
        QuestEventNode* pEventNode = &pNode->event_node_list[i];
        if (pEventNode->ev == proto_ff::E_QUEST_EVENT_CONSUME_ITEM)
        {
            if (uItemGID > 0)
            {
                iRetCode = stBagPageOpMgr.DelItemsByUUid(iItemID, uItemGID);
                CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "stBagPageOpMgr.DelItemsByUUidFromSuitableBagType, iItemID:{} uItemGID:{}", iItemID, uItemGID);
            }
            else
            {
                WillDelItemData delItemData;
                delItemData.m_iItemID = pEventNode->condition;
                delItemData.m_iQuality = iItemQuality;
                delItemData.m_iWantDelNum = pEventNode->condition_value;
                stBagPageOpMgr.DelItems(delItemData);
            }
        }
        else if (pEventNode->ev == proto_ff::E_QUEST_EVENT_USE_ITEM)
        {
            if (uItemGID > 0)
            {
                iRetCode = stBagPageOpMgr.DelItemsByUUid(iItemID, uItemGID);
                CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "stBagPageOpMgr.DelItemsByUUidFromSuitableBagType, iItemID:{} uItemGID:{}", iItemID, uItemGID);
            }
            else
            {
                WillDelItemData delItemData;
                delItemData.m_iItemID = iItemID;
                delItemData.m_iQuality = iItemQuality;
                delItemData.m_iWantDelNum = 1;
                iRetCode = stBagPageOpMgr.DelItems(delItemData);
                CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "DelItemsByUUidFromSuitableBagType Failed, itemId:{} quality:{} num:1", iItemID, iItemQuality);
            }
        }
    }

    proto_ff::Proto_CSRsp resp;
    proto_ff::Proto_CSQuestCompleteRsp* complete_resp = resp.mutable_quest_complete_rsp();
    complete_resp->set_quest_id(iQuestID);

    const E_LoopQuest* pLoopDesc = nullptr;
    LoopQuest* pLoop = nullptr;
    int iLoopQuestIndex = 0;
    bool NotifyTeamMembers = false;
    std::vector<Item> vecAddItems;

    if (pQuestDesc->type == proto_ff::E_Quest_Type_Dungeon)
    {
        LOG_ERR(pPlayer->GetRoleID(), -1, "count pass get other award:{}", iQuestID);
    }
    else
    {
        for (int i = 0; i < pQuestDesc->award_item.size(); ++i)
        {
            Item item;
            item.id = pQuestDesc->award_item[i].id;
            item.value = pQuestDesc->award_item[i].num;
            vecAddItems.push_back(item);
        }

        double exp = 0, money = 0, pet_exp = 0, nian = 0, contribute = 0, coin = 0, bonus = 0;
        NFQuestUtil::CalcQuestExpMoney(pPlayer, pQuestDesc, exp, money, pet_exp, nian, contribute, coin, bonus);

        if (pQuestDesc->type == proto_ff::E_Quest_Type_Protect)
        {
            LoopQuestFinishedNode* phis = pQuestPart->GetLoopQuestHis(iQuestID);
            CHECK_NULL_WF(pPlayer->GetRoleID(), phis, "GetLoopQuestHis Failed:{}", iQuestID);
            phis->last_finished_time = NF_ADJUST_TIMENOW();
            phis->times_in_day++;
        }

        if (pQuestDesc->type == proto_ff::E_Quest_Type_Round)
        {
            // Loop Quest
            // 多倍和单倍仅影响经验
            LoopQuestFinishedNode* phis = pQuestPart->GetLoopQuestHis(iQuestID);
            CHECK_NULL_WF(pPlayer->GetRoleID(), phis, "GetLoopQuestHis Failed:{}", iQuestID);

            pLoopDesc = LoopQuestDesc::Instance()->GetDesc(pQuestDesc->round_group_id);
            CHECK_NULL_WF(pPlayer->GetRoleID(), pLoopDesc, "LoopQuestDesc::GetDesc Failed:{}", pQuestDesc->round_group_id);
            pLoop = pQuestPart->GetLoopQuest(pQuestDesc->round_group_id);
            CHECK_NULL_WF(pPlayer->GetRoleID(), pLoop, "GetLoopQuest Failed:{}", pQuestDesc->round_group_id);

            iLoopQuestIndex = pLoop->node_index;
            float exp_rate = 0;
            iRetCode = GetExpRateForLoopQuest(pPlayer, pLoopDesc, pLoop, &stBagPageOpMgr, exp_rate);
            CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "GetExpRateForLoopQuest Failed:{}", iQuestID);
            exp = exp_rate * exp;
            pet_exp = exp_rate * pet_exp;
            contribute *= 1.0f + pLoopDesc->award_contribute_increte * (pLoop->node_index > 0 ? pLoop->node_index : 1);
            nian *= 1.0f + pLoopDesc->award_nian_increte * (pLoop->node_index > 0 ? pLoop->node_index : 1);
            phis->last_finished_time = NF_ADJUST_TIMENOW();
            phis->times_in_day++;
            if (pLoopDesc->team_quest)
            {
                NotifyTeamMembers = true;
            }
        }

        // TeamAward:
        if (pQuestDesc->award_check_team)
        {
        }

        std::vector<WillAddItemDataWithNum> vecAddDropItem;
        iRetCode = NFDropUtil::Drop(pQuestDesc->award_drop_id, pPlayer->GetLevel(), NFServiceSkill::GetTransferId(pPlayer), vecAddDropItem);
        CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "drop error, dropId:{}", pQuestDesc->award_drop_id);

        iRetCode = stBagPageOpMgr.AddToBag(vecAddDropItem);
        CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "AddItems Failed");

        if (money > 0)
        {
            Item item;
            item.id = proto_ff::EN_ID_MONEY;
            item.value = money;
            vecAddItems.push_back(item);
        }
        if (exp > 0)
        {
            Item item;
            item.id = proto_ff::EN_ID_EXP;
            item.value = exp;
            vecAddItems.push_back(item);
        }
        if (pQuestDesc->award_gold > 0)
        {
            Item item;
            item.id = proto_ff::EN_ID_GOLD;
            item.value = pQuestDesc->award_gold;
            vecAddItems.push_back(item);
        }

        if (pQuestDesc->award_diamond > 0)
        {
            Item item;
            item.id = proto_ff::EN_ID_DIAMOND;
            item.value = pQuestDesc->award_diamond;
            vecAddItems.push_back(item);
        }

        if (contribute > 0)
        {
            Item item;
            item.id = proto_ff::EN_ID_CONTRIBUTION;
            item.value = contribute;
            vecAddItems.push_back(item);
        }
        if (coin > 0)
        {
            Item item;
            item.id = proto_ff::EN_ID_GUILD_COIN;
            item.value = coin;
            vecAddItems.push_back(item);
        }
        if (bonus > 0)
        {
            Item item;
            item.id = proto_ff::EN_ID_GUILD_BOUNS;
            item.value = bonus;
            vecAddItems.push_back(item);
        }
        if (nian > 0)
        {
            Item item;
            item.id = proto_ff::EN_ID_NIAN_SCORE;
            item.value = nian;
            vecAddItems.push_back(item);
        }
    }

    iRetCode = stBagPageOpMgr.AddItems(vecAddItems);
    CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "AddItems Failed");

    if (pQuestDesc->type == proto_ff::E_Quest_Type_Dungeon)
    {
        pQuestPart->AddQuestCount(iQuestID);
    }

    if (pQuestDesc->type == proto_ff::E_Quest_Type_Intrust)
    {
    }
    else
    {
        pQuestPart->DelQuestNode(iQuestID);
    }

    pQuestPart->FinishQuest(iQuestID);

    iRetCode = stBagPageOpMgr.Commit(true);
    CHECK_ERR(pPlayer->GetRoleID(), iRetCode, "Commit iRetCode:{}", iRetCode);

    stBagPageOpMgr.SendRewardNtf(true, proto_ff::EN_REWARD_NOTIFY_TYPE_QUEST, iQuestID);

    NFQuestUtil::OnQuestComplete(pPlayer, iQuestID);

    if (pQuestDesc->type == proto_ff::E_Quest_Type_Round)
    {
        //NextQuest(pPlayer, pLoop, ploopdesc);
        NFPacketSendUtil::SendToClient(pPlayer, proto_ff::E_CS_COMPLETE_QUEST_RSP, &resp);
        /* auto_accept_next_round == 0 为自动接 */
        //if ( pLoop->quest_id && ploopdesc->team_quest && ( ploopdesc->auto_accept_next_round == false || pLoop->node_index != 1 ))
        //    Accept(pPlayer, pLoop->quest_id, true);
    }
    else
    {
        NFPacketSendUtil::SendToClient(pPlayer, proto_ff::E_CS_COMPLETE_QUEST_RSP, &resp);
    }

    return 0;
}
